﻿using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Anagramme.Contracts.Tests
{
    [TestClass]
    public class LobbyInfoTests
    {
        #region GameMode Tests
        [TestMethod]
        public void SetGameModeRaisePropertyChanged()
        {
            string actual = string.Empty;
            string expected = "GameMode";

            LobbyInfo lobby = new LobbyInfo();
            lobby.PropertyChanged += (s, e) => actual = e.PropertyName;
            lobby.GameMode = GameModes.ScoreMode;

            Assert.AreEqual(expected, actual);
        }
        #endregion

        #region MaxWordsLength Tests
        [TestMethod]
        public void SetMaxWordsLengthRaisePropertyChanged()
        {
            string actual = string.Empty;
            string expected = "MaxWordsLength";

            LobbyInfo lobby = new LobbyInfo();
            lobby.PropertyChanged += (s, e) => actual = e.PropertyName;
            lobby.MaxWordsLength = 3;

            Assert.AreEqual(expected, actual);
        }

        [TestMethod]
        public void SetMaxWordsLengthLessThanMinRangeIsInvalid()
        {
            Random random = new Random();
            LobbyInfo lobby = new LobbyInfo();
            lobby.MaxWordsLength = random.Next(5);
            IEnumerable actual = lobby.GetErrors("MaxWordsLength");

            Assert.IsNotNull(actual);
            bool succeed = actual.GetEnumerator().MoveNext();
            Assert.IsTrue(succeed);
        }

        [TestMethod]
        public void SetMaxWordsLengthGreaterThanMinRangeIsInvalid()
        {
            Random random = new Random();
            LobbyInfo lobby = new LobbyInfo();
            lobby.MaxWordsLength = random.Next(9, 1000);
            IEnumerable actual = lobby.GetErrors("MaxWordsLength");

            Assert.IsNotNull(actual);
            bool succeed = actual.GetEnumerator().MoveNext();
            Assert.IsTrue(succeed);
        }

        [TestMethod]
        public void SetMaxWordsLengthInRangeIsValid()
        {
            Random random = new Random();
            LobbyInfo lobby = new LobbyInfo();
            lobby.MaxWordsLength = random.Next(5, 9);
            IEnumerable actual = lobby.GetErrors("MaxWordsLength");

            Assert.IsNotNull(actual);
            bool succeed = actual.GetEnumerator().MoveNext();
            Assert.IsFalse(succeed);
        }
        
        [TestMethod]
        public void SetMaxWordsLengthLessThanMinWordsLengthIsInvalid()
        {
            Random random = new Random();
            LobbyInfo lobby = new LobbyInfo();
            lobby.MaxWordsLength = random.Next(5, 8);
            lobby.MinWordsLength = lobby.MaxWordsLength + 1;
            IEnumerable actual = lobby.GetErrors("MaxWordsLength");

            Assert.IsNotNull(actual);
            bool succeed = actual.GetEnumerator().MoveNext();
            Assert.IsTrue(succeed);
        }
        #endregion

        #region MinWordsLength Tests
        [TestMethod]
        public void SetMinWordsLengthRaisePropertyChanged()
        {
            string actual = string.Empty;
            string expected = "MinWordsLength";

            LobbyInfo lobby = new LobbyInfo();
            lobby.PropertyChanged += (s, e) => actual = e.PropertyName;
            lobby.MinWordsLength = 3;

            Assert.AreEqual(expected, actual);
        }

        [TestMethod]
        public void SetMinWordsLengthLessThanMinRangeIsInvalid()
        {
            Random random = new Random();
            LobbyInfo lobby = new LobbyInfo();
            lobby.MaxWordsLength = 8;
            lobby.MinWordsLength = random.Next(5);
            IEnumerable actual = lobby.GetErrors("MinWordsLength");

            Assert.IsNotNull(actual);
            bool succeed = actual.GetEnumerator().MoveNext();
            Assert.IsTrue(succeed);
        }

        [TestMethod]
        public void SetMinWordsLengthGreaterThanMinRangeIsInvalid()
        {
            Random random = new Random();
            LobbyInfo lobby = new LobbyInfo();
            lobby.MaxWordsLength = 8;
            lobby.MinWordsLength = random.Next(9, 1000);
            IEnumerable actual = lobby.GetErrors("MinWordsLength");

            Assert.IsNotNull(actual);
            bool succeed = actual.GetEnumerator().MoveNext();
            Assert.IsTrue(succeed);
        }

        [TestMethod]
        public void SetMinWordsLengthInRangeIsValid()
        {
            Random random = new Random();
            LobbyInfo lobby = new LobbyInfo();
            lobby.MaxWordsLength = 8;
            lobby.MinWordsLength = random.Next(5, 9);
            IEnumerable actual = lobby.GetErrors("MinWordsLength");

            Assert.IsNotNull(actual);
            bool succeed = actual.GetEnumerator().MoveNext();
            Assert.IsFalse(succeed);
        }

        [TestMethod]
        public void SetMaxMinWordsLengthGreaterThanWordsLengthIsInvalid()
        {
            Random random = new Random();
            LobbyInfo lobby = new LobbyInfo();
            lobby.MaxWordsLength = random.Next(5, 8);
            lobby.MinWordsLength = lobby.MaxWordsLength + 1;
            IEnumerable actual = lobby.GetErrors("MinWordsLength");

            Assert.IsNotNull(actual);
            bool succeed = actual.GetEnumerator().MoveNext();
            Assert.IsTrue(succeed);
        }
        #endregion

        #region TargetRounds Tests
        [TestMethod]
        public void SetTargetRoundsRaisePropertyChanged()
        {
            string actual = string.Empty;
            string expected = "TargetRounds";

            LobbyInfo lobby = new LobbyInfo();
            lobby.PropertyChanged += (s, e) => actual = e.PropertyName;
            lobby.TargetRounds = 3;

            Assert.AreEqual(expected, actual);
        }

        [TestMethod]
        public void SetTargetRoundsLessThanMinRangeIsInvalid()
        {
            LobbyInfo lobby = new LobbyInfo();
            lobby.TargetRounds = 0;
            IEnumerable actual = lobby.GetErrors("TargetRounds");

            Assert.IsNotNull(actual);
            bool succeed = actual.GetEnumerator().MoveNext();
            Assert.IsTrue(succeed);
        }

        [TestMethod]
        public void SetTargetRoundsGreaterThanMinRangeIsInvalid()
        {
            Random random = new Random();
            LobbyInfo lobby = new LobbyInfo();
            lobby.TargetRounds = random.Next(101, 1000);
            IEnumerable actual = lobby.GetErrors("TargetRounds");

            Assert.IsNotNull(actual);
            bool succeed = actual.GetEnumerator().MoveNext();
            Assert.IsTrue(succeed);
        }

        [TestMethod]
        public void SetTargetRoundsInRangeIsValid()
        {
            Random random = new Random();
            LobbyInfo lobby = new LobbyInfo();
            lobby.TargetRounds = random.Next(1, 101);
            IEnumerable actual = lobby.GetErrors("TargetRounds");

            Assert.IsNotNull(actual);
            bool succeed = actual.GetEnumerator().MoveNext();
            Assert.IsFalse(succeed);
        }
        #endregion

        #region TargetScore Tests
        [TestMethod]
        public void SetTargetScoreRaisePropertyChanged()
        {
            string actual = string.Empty;
            string expected = "TargetScore";

            LobbyInfo lobby = new LobbyInfo();
            lobby.PropertyChanged += (s, e) => actual = e.PropertyName;
            lobby.TargetScore = 3;

            Assert.AreEqual(expected, actual);
        }

        [TestMethod]
        public void SetTargetScoreLessThanMinRangeIsInvalid()
        {
            Random random = new Random();
            LobbyInfo lobby = new LobbyInfo();
            lobby.TargetScore = random.Next(10);
            IEnumerable actual = lobby.GetErrors("TargetScore");

            Assert.IsNotNull(actual);
            bool succeed = actual.GetEnumerator().MoveNext();
            Assert.IsTrue(succeed);
        }

        [TestMethod]
        public void SetTargetScoreGreaterThanMinRangeIsInvalid()
        {
            Random random = new Random();
            LobbyInfo lobby = new LobbyInfo();
            lobby.TargetScore = random.Next(101, 1000);
            IEnumerable actual = lobby.GetErrors("TargetScore");

            Assert.IsNotNull(actual);
            bool succeed = actual.GetEnumerator().MoveNext();
            Assert.IsTrue(succeed);
        }

        [TestMethod]
        public void SetTargetScoreInRangeIsValid()
        {
            Random random = new Random();
            LobbyInfo lobby = new LobbyInfo();
            lobby.TargetScore = random.Next(10, 101);
            IEnumerable actual = lobby.GetErrors("TargetScore");

            Assert.IsNotNull(actual);
            bool succeed = actual.GetEnumerator().MoveNext();
            Assert.IsFalse(succeed);
        }
        #endregion
    }
}
